﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Xunit;
using M3G;

/**
 * スキニング(ボーン行列をかける)のはシェーダーの中(m3g_ffunction())
 * */

namespace MyTestProject {
    public class TestSkinnedMesh {
        [Fact]
        public void TestConstructor () {
            var skel = new Group ();
            var mesh = new SkinnedMesh (2, 0, skel);

            Assert.Equal (skel, mesh.Skeleton);
            Assert.Equal (0, mesh.BoneCount);
        }

        [Fact]
        public void TestSetBones () {
            var skel = new Group ();
            var mesh = new SkinnedMesh (2, 0, skel);

            var bone1 = new Group ();
            var bone2 = new Group ();
            skel.AddChild (bone1);
            skel.AddChild (bone2);

            mesh.SetBones (new Node[] { skel, bone1, bone2 });

            Assert.Equal (3, mesh.BoneCount);
            Assert.Equal (skel, mesh.Bones[0]);
            Assert.Equal (bone1, mesh.Bones[1]);
            Assert.Equal (bone2, mesh.Bones[2]);
        }

        [Fact]
        public void TestGetBoneTransform () {
            var skel = new Group ();
            var bone = new Group ();
            skel.AddChild (bone);
            skel.PostRotate (45f, 1, 0, 0);

            var mesh = new SkinnedMesh (2, 0, skel);
            mesh.SetBones (new Node[] { skel, bone});

            var expected = mesh.GetTransformTo (bone);
       
            Assert.Equal (expected, mesh.BoneTransform (bone));
        }

        [Fact]
        public void TestReferences () {
            var skel = new Group ();
            var bone1 = new Group ();
            var bone2 = new Group ();
            skel.AddChild (bone1);
            skel.AddChild (bone2);

            var msh = new SkinnedMesh (2, 0, skel);
      
            var refs = msh.References;

            Assert.Equal (3, refs.Length);
            Assert.Equal (skel, refs[0]);
            Assert.Equal (bone2, refs[1]);
            Assert.Equal (bone1, refs[2]);
        }

        /**
         * 複製のテスト
         * ボーン階層も全て複製されるのでスケルトンノードは複製前後で同じインスタンスであってはならない。
         * また複製後のボーンを使って複製前と等しいボーン変換行列が取得できなければならない。
         * (注意:TransformはStruct型なので値渡し)
         * */
        [Fact]
        public void TestDuplicate () {
            var skel = new Group ();
            var msh = new SkinnedMesh (2, 0, skel);
            
            var bone1 = new Group ();
            var bone2 = new Group ();
            skel.AddChild (bone1);
            skel.AddChild (bone2);

            msh.SetBones (new Node[] { skel, bone1, bone2 });
            msh.UserID = 100;

            var grp = new Group ();
            grp.AddChild (msh);

            var dup = (SkinnedMesh)msh.Duplicate ();

            Assert.Equal (null, dup.Parent);
            Assert.Equal (msh.BoneCount, dup.BoneCount);
            Assert.Equal (msh.BoneTransform (msh.Bones[0]), dup.BoneTransform (dup.Bones[0]));
            Assert.Equal (msh.BoneTransform (msh.Bones[1]), dup.BoneTransform (dup.Bones[1]));
            Assert.Equal (msh.UserID, dup.UserID);
            Assert.NotSame (msh.Skeleton, dup.Skeleton);
            Assert.NotSame (msh.Bones[0], dup.Bones[0]);
            Assert.NotSame (msh.Bones[1], dup.Bones[1]);
        }

    }


}
